/*=============================================================================
    Spirit v1.6.0
    Copyright (c) 1998-2003 Joel de Guzman
    http://spirit.sourceforge.net/

    Permission to copy, use, modify, sell and distribute this software is
    granted provided this copyright notice appears in all copies. This
    software is provided "as is" without express or implied warranty, and
    with no claim as to its suitability for any purpose.
=============================================================================*/
#if !defined(BOOST_SPIRIT_SKIPPER_HPP)
#define BOOST_SPIRIT_SKIPPER_HPP

///////////////////////////////////////////////////////////////////////////////
#include <cctype>

#include "boost/spirit/core/scanner/scanner.hpp"
#include "boost/spirit/core/primitives/impl/primitives.ipp"

///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit {

template <typename BaseT>
struct no_skipper_iteration_policy; // forward

///////////////////////////////////////////////////////////////////////////////
//
//  skipper_iteration_policy class
//
///////////////////////////////////////////////////////////////////////////////
template <typename BaseT = iteration_policy>
struct skipper_iteration_policy : public BaseT
{
    typedef BaseT base_t;

    skipper_iteration_policy()
    : BaseT() {}

    template <typename PolicyT>
    skipper_iteration_policy(PolicyT const& other)
    : BaseT(other) {}

    template <typename ScannerT>
    void
    advance(ScannerT const& scan) const
    {
        BaseT::advance(scan);
        scan.skip(scan);
    }

    template <typename ScannerT>
    bool
    at_end(ScannerT const& scan) const
    {
        scan.skip(scan);
        return BaseT::at_end(scan);
    }

    template <typename ScannerT>
    void
    skip(ScannerT const& scan) const
    {
        while (!BaseT::at_end(scan) && impl::isspace_(BaseT::get(scan)))
            BaseT::advance(scan);
    }
};

///////////////////////////////////////////////////////////////////////////////
//
//  skipper_iteration_policy class
//
///////////////////////////////////////////////////////////////////////////////
    namespace impl
    {
        template <typename ST, typename ScannerT, typename BaseT>
        void
        skipper_skip(
            ST const& s,
            ScannerT const& scan,
            skipper_iteration_policy<BaseT> const&);

        template <typename ST, typename ScannerT, typename BaseT>
        void
        skipper_skip(
            ST const& s,
            ScannerT const& scan,
            no_skipper_iteration_policy<BaseT> const&);

        template <typename ST, typename ScannerT>
        void
        skipper_skip(
            ST const& s,
            ScannerT const& scan,
            iteration_policy const&);
    }

template <typename ParserT, typename BaseT = iteration_policy>
class skip_parser_iteration_policy : public skipper_iteration_policy<BaseT>
{
public:

    typedef skipper_iteration_policy<BaseT> base_t;

    skip_parser_iteration_policy(
        ParserT const& skip_parser,
        base_t const& base = base_t())
    : base_t(base), subject(skip_parser) {}

    template <typename PolicyT>
    skip_parser_iteration_policy(PolicyT const& other)
    : base_t(other), subject(other.skipper()) {}

    template <typename ScannerT>
    void
    skip(ScannerT const& scan) const
    {
        impl::skipper_skip(subject, scan, scan);
    }

    ParserT const&
    skipper() const
    { return subject; }

private:

    ParserT const& subject;
};

///////////////////////////////////////////////////////////////////////////////
//
//  Free parse functions using the skippers
//
///////////////////////////////////////////////////////////////////////////////
template <typename IteratorT, typename ParserT, typename SkipT>
parse_info<IteratorT>
parse(
    IteratorT const&        first,
    IteratorT const&        last,
    parser<ParserT> const&  p,
    parser<SkipT> const&    skip);

///////////////////////////////////////////////////////////////////////////////
//
//  Parse function for null terminated strings using the skippers
//
///////////////////////////////////////////////////////////////////////////////
template <typename CharT, typename ParserT, typename SkipT>
parse_info<CharT const*>
parse(
    CharT const*            str,
    parser<ParserT> const&  p,
    parser<SkipT> const&    skip);

///////////////////////////////////////////////////////////////////////////////
//
//  phrase_scanner_t
//
//      The most common scanner. Use this typedef when you need
//      a scanner that skips white spaces.
//
///////////////////////////////////////////////////////////////////////////////
typedef skipper_iteration_policy<>                  iter_policy_t;
typedef scanner_policies<iter_policy_t>             scanner_policies_t;
typedef scanner<char const*, scanner_policies_t>    phrase_scanner_t;

///////////////////////////////////////////////////////////////////////////////
}} // namespace boost::spirit

#include "boost/spirit/core/scanner/impl/skipper.ipp"
#endif

